home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1990
/
10
/
switzer.asc
< prev
next >
Wrap
Text File
|
1990-08-16
|
14KB
|
321 lines
_CLOSING DOS'S BACKDOOR_
by John Switzer
[LISTING ONE]
TITLE - BACKDOOR.SYS - closes DOS's backdoors
PAGE 60,132
.RADIX 16
; BACKDOOR.SYS closes two "backdoors" into the MS-DOS INT 21h function
; dispatcher that could be used by a virus or trojan horse to cause damage.
; It also filters INT 21h directly to reject a special case of function 13h
; which could destroy all data on a disk.
; For use with MASM 5.1
; MASM BACKDOOR;
; LINK BACKDOOR;
; EXE2BIN BACKDOOR.EXE BACKDOOR.SYS
;
ASSUME CS:CSEG, DS:CSEG
CSEG SEGMENT PARA PUBLIC 'CODE'
ORG 0000h ; device driver starts at 0
DW 0FFFFh,0FFFFh ; far pointer to next device
DW 8000h ; character device driver
DW offset DEV_STRAT_RTN ; pointer to the strategy routine
DW offset DEV_INT_RTN ; pointer to the interrupt routine
DB "B"+80h,"ACKDOOR" ; device name with high bit set will
; avoid any filename conflicts
INSTALL_MSG DB 0Dh,0Ah
DB "BACKDOOR is installed at $"
DEV_HDR_BX DW 0000 ; pointer for ES:BX for device
DEV_HDR_ES DW 0000 ; request header
ORIG_INT21_OFF DW 0000 ;
ORIG_INT21_SEG DW 0000 ;
TEMP DW 0000 ; used for temporary storage
REFUSE_RQST PROC FAR ;
POP AX ; get rid of flags on stack
POP AX ; get the return segment
POP CS:TEMP ; and save offset
PUSH AX ; save the return address in proper
PUSH CS:TEMP ; order
STC ; return STC for error
MOV AX,0FFFFh ; return AX=-1
RET ; and do FAR RET back to caller
REFUSE_RQST ENDP
NEW_INT21 PROC NEAR
PUSH AX ; save original registers first thing
PUSH BX
CMP AH,13h ; is this the DELETE FCB function?
JNZ CONT_ORIG_INT21 ; no, so continue on
MOV BX,DX ; point BX to the FCB
CMP byte ptr DS:[BX],0FFh ; got an extended FCB?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP byte ptr DS:[BX+6],1Fh; yes, so got the special attribute?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP word ptr DS:[BX+8],"??"; yes, so filename starts with "??" ?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP word ptr DS:[BX+0Ah],"??"; yes, so filename = "??" ?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP word ptr DS:[BX+0Ch],"??"; yes, so filename = "??" ?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP word ptr DS:[BX+0Eh],"??"; yes, so filename = "??" ?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP word ptr DS:[BX+10h],"??"; yes, so filename = "??" ?
JNZ CONT_ORIG_INT21 ; no, so continue on
CMP byte ptr DS:[BX+12h],"?"; yes, so filename ends with "??" ?
JNZ CONT_ORIG_INT21 ; no, so continue on
POP BX ; yes, so reject it altogether
POP AX ;
MOV AL,0FFh ; return match not found
STC ; STC just for the heck of it
RETF 0002 ; and IRET with new flags
CONT_ORIG_INT21:
POP BX ; restore original registers
POP AX ;
JMP dword ptr CS:ORIG_INT21_OFF; continue with original handler
NEW_INT21 ENDP
DEV_STRAT_RTN PROC FAR ;
MOV CS:DEV_HDR_BX,BX ; save the ES:BX pointer to the
MOV CS:DEV_HDR_ES,ES ; device request header
RET ;
DEV_STRAT_RTN ENDP
DEV_INT_RTN PROC FAR ;
PUSH AX ; save all registers
PUSH BX ;
PUSH CX ;
PUSH DX ;
PUSH DS ;
PUSH ES ;
PUSH DI ;
PUSH SI ;
PUSH BP ;
PUSH CS ;
POP DS ; point DS to local code
LES DI,dword ptr DEV_HDR_BX; ES:DI=device request header
MOV BL,ES:[DI+02] ; get the command code
XOR BH,BH ; clear out high byte
CMP BX,00h ; doing an INSTALL?
JNZ DEV_IGNORE ; no, so just ignore the call then
CALL INSTALL_BACKDOOR ; yes, so install code in memory
DEV_IGNORE: ;
MOV AX,0100h ; return STATUS of DONE
LDS BX,dword ptr CS:DEV_HDR_BX; DS:BX=device request header
MOV [BX+03],AX ; return STATUS in the header
POP BP ; restore original registers
POP SI ;
POP DI ;
POP ES ;
POP DS ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
RET ; and RETF to DOS
DEV_INT_RTN ENDP
INSTALL_BACKDOOR PROC NEAR ;
CALL CLOSE_BACK_DOOR ; install new handler to close back
; door
CALL HOOK_INT21 ; and hook INT21 filter
MOV AH,09h ; DOS display string
MOV DX,offset INSTALL_MSG ; show installation message
INT 21h ; via DOS
MOV AX,CS ; display current code segment
CALL OUTPUT_AX_AS_HEX ; output AX as two HEX digits
MOV AL,3Ah ; now output a colon
CALL DISPLAY_TTY ; to the screen
MOV AX,offset REFUSE_RQST ; show new handler's offset
CALL OUTPUT_AX_AS_HEX ; output AX as two HEX digits
CALL DISPLAY_NEWLINE ; output a newline to finish display
LES DI,dword ptr DEV_HDR_BX; ES:DI=device request header
MOV Word Ptr ES:[DI+0Eh],offset INSTALL_BACKDOOR; this is the
MOV ES:[DI+10h],CS ; end of resident code
RET ;
INSTALL_BACKDOOR ENDP
CLOSE_BACK_DOOR PROC NEAR ;
PUSH ES ; save original registers
PUSH AX ;
PUSH BX ;
XOR AX,AX ; point ES to the interrupt vector
MOV ES,AX ; table
MOV BX,00C1h ; install new handler at INT30 + 1
MOV AX,offset REFUSE_RQST ; get new offset for the handler
MOV ES:[BX],AX ; save it in interrupt vector table
MOV AX,CS ; get the segment for the handler
MOV ES:[BX+02],AX ; and save it, too
POP BX ; restore original registers
POP AX ;
POP ES ;
RET ; and RET to caller
CLOSE_BACK_DOOR ENDP
HOOK_INT21 PROC NEAR
PUSH AX
PUSH BX
PUSH ES
MOV AX,3521h ; get current INT21 vector
INT 21h ; via DOS
MOV CS:ORIG_INT21_OFF,BX ; save the offset
MOV BX,ES ;
MOV CS:ORIG_INT21_SEG,BX ; and the segment
PUSH CS
POP DS ; make sure DS=local code
MOV DX,offset NEW_INT21 ; point to new handler
MOV AX,2521h ; install new handler
INT 21h ; via DOS
POP ES ; and restore original registers
POP BX
POP AX
RET ; and RET to caller
HOOK_INT21 ENDP
OUTPUT_AX_AS_HEX PROC NEAR ;
PUSH AX ; save original registers
PUSH BX ;
PUSH CX ;
PUSH AX ; save number for output
MOV AL,AH ; output high byte first
CALL OUTPUT_AL_AS_HEX ; output AL as two HEX digits
POP AX ; output low byte next
CALL OUTPUT_AL_AS_HEX ; output AL as two HEX digits
POP CX ; restore original registers
POP BX ;
POP AX ;
RET ; and RET to caller
OUTPUT_AX_AS_HEX ENDP
OUTPUT_AL_AS_HEX PROC NEAR ;
PUSH AX ; save original registers
PUSH BX ;
PUSH CX ;
PUSH AX ; save the number for output (in AL)
MOV CL,04h ; first output high nibble
SHR AL,CL ; get digit into low nibble
ADD AL,30h ; convert to ASCII
CMP AL,39h ; got a decimal digit?
JBE OUTPUT_FIRST_DIGIT ; yes, so continue
ADD AL,07h ; no, so convert to HEX ASCII
OUTPUT_FIRST_DIGIT: ;
CALL DISPLAY_TTY ; output it via BIOS
POP AX ; get number back
AND AL,0Fh ; keep only low digit now
ADD AL,30h ; convert to ASCII
CMP AL,39h ; got a decimal digit?
JBE OUTPUT_SECOND_DIGIT ; yes, so continue
ADD AL,07h ; no, so convert to HEX ASCII
OUTPUT_SECOND_DIGIT:
CALL DISPLAY_TTY ; output it via BIOS
POP CX ; restore original registers
POP BX ;
POP AX ;
RET ; and RET to caller
OUTPUT_AL_AS_HEX ENDP
DISPLAY_NEWLINE PROC NEAR ;
PUSH AX ; save original AX
MOV AL,0Dh ; first do CR
CALL DISPLAY_TTY ; output it via the BIOS
MOV AL,0Ah ; do LF next
CALL DISPLAY_TTY ; output it via the BIOS
POP AX ; restore original AX
RET ; and RET to caller
DISPLAY_NEWLINE ENDP
DISPLAY_TTY PROC NEAR ;
PUSH AX ;
PUSH BX ;
MOV AH,0Eh ; display TTY
MOV BX,0007h ; on page 0, normal attribute
INT 10h ; via BIOS
POP BX ;
POP AX ;
RET ;
DISPLAY_TTY ENDP
CSEG ENDS
END
[Examplσ 1║ Aε alternativσ entr∙ poin⌠ int∩ MS-DOS 3.30 ]
ALT_DOS_ENTRY:
POP AX ; get rid of flags
POP AX ; save caller's segment
POP CS:TEMP ; save caller's offset
PUSHF ; save flags
CLI ; kill interrupts
PUSH AX ; save caller's segment
PUSH CS:TEMP ; save caller's offset
CMP CL,24h ; is CL < max #?
JA REFUSE_RQST ; no, so invalid
MOV AH,CL ; yes, AH=function #
JMP CONT_INT21 ; and continue INT21
[Examplσ 2║ ┴ fa≥ jum≡ execute≤ thσ cal∞ anΣ thσ dispatche≥ ì
return≤ t∩ thσ stack]
MOV AX,offset RETURN ; get return address' offset
PUSH AX ; push flags and return address
PUSH CS ; onto stack in reverse order
PUSHF ;
MOV CL,9 ; display DOS string
MOV DX,offset MSG ; this is the message
PUSH CS
POP DS ; verify that DS = local code
JMP dword ptr ALT_DOS_PTR ; and execute the function
RETURN:
MOV AH,4Ch ; terminate a process
INT 21h ; via DOS
ALT_DOS_PTR DW 00C0h,0000 ; entry point for alternative
; DOS handler (0:00C0h)
MSG DB 0Dh,0Ah,"Example of backdoor MS-DOS "
DB "function call.",0Dh,0Ah,7,"$"
[Examplσ 3║ Aε FC┬ functioε caε deletσ files« NOTEí Callinτ thi≤ ì
functioε whilσ a⌠ thσ roo⌠ director∙ wil∞ obliteratσ al∞ file≤ oε ì
thσ disk¼ requirinτ ver∙ tediou≤ worδ witΦ you≥ favoritσ disδ ì
edito≥ t∩ restorσ them« ]
MOV AX,offset RETURN ; get return address' offset
PUSH AX ; push flags and return address
PUSH CS ; onto stack in reverse order
PUSHF ;
MOV CL,13h ; DELETE FCB function
MOV DX,offset FCB ; this is the special FCB
PUSH CS p73
POP DS ; verify that DS = local code
JMP dword ptr ALT_DOS_PTR ; and execute the function
RETURN:
MOV AH,4Ch ; terminate the process
INT 21h ; via DOS
ALT_DOS_PTR DW 00C0h,0000 ; entry point for alternative
; DOS handler (0:00C0h)
FCB DB 0FFh ; extended FCB
DB 5 dup(0) ; reserved bytes
DB 1Fh ; all attribute bits set
DB 0 ; default drive ID
DB "???????????" ; match all files
DB 19h dup(0) ; rest of FCB